package com.platform.netty.udp.handler;

import com.platform.common.manager.AsyncManager;
import com.platform.common.utils.netty.ChannelSupervise;
import com.platform.common.utils.netty.NettyUtil;
import com.platform.common.utils.redis.RedisUtil;
import com.platform.netty.udp.task.TempPoolTask;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;

@Component
@ChannelHandler.Sharable
@Slf4j
public class UdpServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 活跃的、有效的通道
     * 第一次连接成功后进入的方法
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        String ip = getRemoteAddress(ctx);
        if(!redisUtil.hHasKey("netty-error",ip)){
            String channelId = ctx.channel().id().asLongText();
            log.info("与tcp客户端" + getRemoteAddress(ctx) + "建立连接，通道开启！channelActive 被调用" + channelId);
            //将tcp客户端的channel信息保存
            ChannelSupervise.addChannel(ctx.channel());
        }else{
            ctx.disconnect();
        }
    }

    /**
     * 获取client对象：ip
     *
     * @param ctx
     * @return
     */
    private String getRemoteAddress(ChannelHandlerContext ctx) {
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String ip = insocket.getAddress().getHostAddress();
        return ip;
    }

    /**
     * 拿到传过来的msg数据，开始处理
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) {
        log.info("UDP客户端地址"+msg.sender().getHostString()+"端口："+msg.sender().getPort());
        String datas = NettyUtil.hexByteStr(msg.content());
        log.info("UDP服务端接收到" + ctx.channel().id().asLongText() + "的数据: " + datas);
        //将数据保存到redis
        this.saveTemp(datas);
    }

    /**
     * 将数据保存到数据库
     * @param datas
     */
    private void saveTemp(String datas){
        AsyncManager.me().execute(TempPoolTask.saveTemp(datas));
    }

    /**
     * 异常处理
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        //发生异常，关闭连接
        log.error("通道发生异常，即将断开连接");
        ctx.disconnect();//再次建议close
    }
}
